package com.coflxl.web.api.common.service.impl;

import com.coflxl.common.handler.ApiExceptionHandler;
import com.coflxl.common.model.SysCommonSqlVo;
import com.coflxl.web.config.DynamicDataSourceRegister;
import org.sagacity.sqltoy.SqlToyContext;
import org.sagacity.sqltoy.dao.SqlToyLazyDao;
import org.sagacity.sqltoy.dao.impl.SqlToyLazyDaoImpl;
import org.sagacity.sqltoy.model.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;

@Component
public class DynamicQueryExecutor {
    @Autowired
    private SqlToyLazyDao sqlToyLazyDao;
    /**
     * 在动态数据源中执行查询
     * @param key 配置键
     * @param params 查询参数
     * @param function 查询函数
     * @return 查询结果
     */
    public  <T> T executeQuery(String key,
                                     Map<String, Object> params,
                                     BiFunction<SqlToyLazyDao, String, T> function) throws Exception {
        // 1. 获取SQL配置
        params.put("key", key);
        SysCommonSqlVo sqlConfig = sqlToyLazyDao.loadBySql(
                "sys_common_sql_findBySqlId",
                params,
                SysCommonSqlVo.class);
        if (sqlConfig == null) {
            throw new ApiExceptionHandler("未找到key相关配置: " + key);
        }
        // 2. 获取数据源
        DataSource targetDs = DynamicDataSourceRegister.getDataSource(sqlConfig.getDb());
        if (targetDs == null) {
            throw new RuntimeException("未找到数据源：" + sqlConfig.getDb());
        }
        // 3. 创建临时上下文和DAO
        SqlToyContext tempContext = null;
        SqlToyLazyDaoImpl tempDao = null;
        try {
            tempContext = new SqlToyContext();
            tempContext.setDialect(DynamicDataSourceRegister.getDialect(sqlConfig.getDb()));
            tempContext.setDefaultDataSource(targetDs);
            tempContext.initialize();

            tempDao = new SqlToyLazyDaoImpl();
            tempDao.setSqlToyContext(tempContext);
            tempDao.setDataSource(targetDs);

            // 4. 执行查询
            return function.apply(tempDao, sqlConfig.getSqlContent());
        } finally {
            // 5. 清理资源
            if (tempContext != null) {
                tempContext.destroy();
            }
        }
    }

    /**
     * 执行分页查询
     */
    public  Page<Map> executePageQuery(String key,
                                             Page pageDto,
                                             Map<String, Object> params) throws Exception {
        return executeQuery(key, params, (dao, sql) -> {
            return dao.findPageBySql(pageDto, sql, params, Map.class);
        });
    }

    /**
     * 执行列表查询
     */
    public  List<Map> executeListQuery(String key, Map<String, Object> params) throws Exception {
        return executeQuery(key, params, (dao, sql) -> {
            return dao.findBySql(sql, params, Map.class);
        });
    }

    /**
     * 执行单条查询
     */
    public  Map executeSingleQuery(String key, Map<String, Object> params) throws Exception {
        return executeQuery(key, params, (dao, sql) -> {
            return dao.loadBySql(sql, params, Map.class);
        });
    }
    /**
     * 执行单条查询
     */
    public  Long executeSingleAdd(String key, Map<String, Object> params) throws Exception {
        return executeQuery(key, params, (dao, sql) -> {
            return dao.executeSql(sql, params);
        });
    }
}
